package fs

import (
	"github.com/sirupsen/logrus"
	"mydocker/cgroups/resource"
	"mydocker/common"
	"os"
	"path"
	"strconv"
)

type MemorySubsystem struct {
}

// Name 返回 cgroup 名字
func (*MemorySubsystem) Name() string {
	return "memory"
}

// Set 设置 cgroupPath 对应的 cgroup 的内存资源限制
func (m *MemorySubsystem) Set(cgroupPath string, res *resource.ResourceConfig) error {
	if res.MemoryLimit == "" {
		return nil
	}
	subSystemCgroupPath, err := getCgroupPath(m.Name(), cgroupPath, true)
	if err != nil {
		logrus.Errorf("get %s path, err: %v", cgroupPath, err)
		return err
	}
	logrus.Infof("memory subsystemCgroupPath: %s", subSystemCgroupPath)
	// 设置 cgroup 内存限制
	// 将这个限制写入到 cgroup 对应目录的 memory.limit_in_bytes 文件中即可
	// 如果路径不存在，os.WriteFile 会创建一个新文件，如果文件已存在，会覆盖文件原有内容
	if err = os.WriteFile(path.Join(subSystemCgroupPath, "memory.limit_in_bytes"), []byte(res.MemoryLimit), common.Perm0644); err != nil {
		return err
	}
	logrus.Infof("memory limit: %s", res.MemoryLimit)
	return nil
}

func (m *MemorySubsystem) Apply(cgroupPath string, pid int) error {
	subsystemCgroupPath, err := getCgroupPath(m.Name(), cgroupPath, true)
	if err != nil {
		logrus.Errorf("get %s path, err: %v", cgroupPath, err)
		return err
	}
	tasksPath := path.Join(subsystemCgroupPath, "tasks")
	if err = os.WriteFile(tasksPath, []byte(strconv.Itoa(pid)), common.Perm0644); err != nil {
		logrus.Errorf("memory write pid to tasks, path: %s, pid: %d, err: %v", tasksPath, pid, err)
		return err
	}
	return nil
}

func (m *MemorySubsystem) Remove(cgroupPath string) error {
	subsystemCgroupPath, err := getCgroupPath(m.Name(), cgroupPath, false)
	if err != nil {
		logrus.Errorf("get %s path, err: %v", cgroupPath, err)
		return err
	}
	return os.RemoveAll(subsystemCgroupPath) // 删除指定的文件或目录，以及任何子目录和子文件
}
